Feature/UI improvements#1194
Conversation
There was a problem hiding this comment.
Pull Request Overview
This pull request implements a comprehensive UI/UX overhaul including new navigation, search functionality, profile features, and settings redesign. The changes add clickable usernames, profile badges for followed users, recent search history, enhanced settings with nested routes, profile statistics, and mouse navigation support.
Key Changes
- Added clickable usernames and profile badges indicating followed users
- Implemented recent search history with keyboard navigation
- Redesigned settings UI with categorized sections and nested routing
- Added profile statistics (following count) and "View as" context menu option
- Implemented mouse back/forward button navigation for columns
Reviewed Changes
Copilot reviewed 34 out of 34 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
| crates/notedeck_ui/src/widgets.rs | Added new button widgets (rounded, segmented) and helper functions for side panel styling |
| crates/notedeck_ui/src/username.rs | Made usernames clickable and added unused helper function |
| crates/notedeck_ui/src/profile/picture.rs | Added badge display for followed users on profile pictures |
| crates/notedeck_ui/src/profile/mod.rs | Added expandable/truncatable about section variants |
| crates/notedeck_ui/src/note/mod.rs | Made note headers clickable to navigate to profiles |
| crates/notedeck_columns/src/ui/widgets.rs | Added UserRow widget for displaying user information |
| crates/notedeck_columns/src/ui/side_panel.rs | Major redesign with new navigation buttons and connectivity indicator |
| crates/notedeck_columns/src/ui/settings.rs | Complete settings UI redesign with nested routes and modern layout |
| crates/notedeck_columns/src/ui/search/mod.rs | Added recent search history, keyboard navigation, and user search suggestions |
| crates/notedeck_columns/src/ui/search/state.rs | Added Default derive for FocusState enum |
| crates/notedeck_columns/src/ui/profile/mod.rs | Added profile statistics display and contacts list view |
| crates/notedeck_columns/src/route.rs | Added SettingsRoute enum and Following/FollowedBy routes |
| crates/notedeck_columns/src/app.rs | Added mouse back/forward navigation and hovered column tracking |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| fn ui_abbreviate_name_clickable(ui: &mut egui::Ui, name: &str, len: usize, color: Option<Color32>) -> bool { | ||
| let should_abbrev = name.len() > len; | ||
| let name = if should_abbrev { | ||
| let closest = notedeck::abbrev::floor_char_boundary(name, len); | ||
| &name[..closest] | ||
| } else { | ||
| name | ||
| }; | ||
|
|
||
| let resp1 = ui.add(egui::Label::new(colored_name(name, color)).sense(egui::Sense::click())); | ||
|
|
||
| let resp2 = if should_abbrev { | ||
| ui.add(egui::Label::new(colored_name("..", color)).sense(egui::Sense::click())) | ||
| } else { | ||
| resp1.clone() | ||
| }; | ||
|
|
||
| resp1.clicked() || resp2.clicked() | ||
| } |
There was a problem hiding this comment.
The function ui_abbreviate_name_clickable is defined but never used in the codebase. This appears to be dead code that should either be removed or integrated into the username clickability implementation if it was intended to replace the current approach.
| mod state; | ||
|
|
||
| pub use state::{FocusState, SearchQueryState, SearchState}; | ||
| pub use state::{FocusState, RecentSearchItem, SearchQueryState, SearchState}; |
There was a problem hiding this comment.
RecentSearchItem is exported from the state module but is not defined in state.rs. This will cause a compilation error. The type needs to be defined in the state module or the export should be removed.
| pub use state::{FocusState, RecentSearchItem, SearchQueryState, SearchState}; | |
| pub use state::{FocusState, SearchQueryState, SearchState}; |
| }) | ||
| SearchState::New | SearchState::Navigating | SearchState::Typing(TypingType::Mention(_)) => { | ||
| if !self.query.string.is_empty() && !self.query.string.starts_with('@') { | ||
| self.query.user_results = self.note_context.ndb.search_profile(self.txn, &self.query.string, 10) |
There was a problem hiding this comment.
The field user_results is accessed on SearchQueryState but is not defined in the struct in state.rs. This field needs to be added to the SearchQueryState struct definition.
| self.handle_mention_search(ui, &mut search_action); | ||
| } else { | ||
| self.query.user_results.clear(); | ||
| self.query.selected_index = -1; |
There was a problem hiding this comment.
The field selected_index is accessed on SearchQueryState but is not defined in the struct in state.rs. This field needs to be added to the SearchQueryState struct definition.
| } | ||
|
|
||
| fn show_recent_searches(&mut self, ui: &mut egui::Ui, keyboard_resp: KeyboardResponse) -> Option<SearchAction> { | ||
| if self.query.recent_searches.is_empty() { |
There was a problem hiding this comment.
The field recent_searches is accessed on SearchQueryState but is not defined in the struct in state.rs. This field needs to be added to the SearchQueryState struct definition with an appropriate type (likely Vec<RecentSearchItem>).
| ui.label("Recent"); | ||
| ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| { | ||
| if ui.button(RichText::new("Clear all").size(14.0)).clicked() { | ||
| self.query.clear_recent_searches(); |
There was a problem hiding this comment.
The method clear_recent_searches is called on SearchQueryState but is not defined. This method needs to be implemented on the SearchQueryState type.
| } | ||
|
|
||
| if resp.secondary_clicked() || (is_selected && ui.input(|i| i.key_pressed(Key::Delete))) { | ||
| self.query.remove_recent_search(i); |
There was a problem hiding this comment.
The method remove_recent_search is called on SearchQueryState but is not defined. This method needs to be implemented on the SearchQueryState type to handle removal of search history items by index.
| None | ||
| } | ||
| SearchAction::NavigateToProfile(pubkey) => { | ||
| state.add_recent_profile(pubkey, state.string.clone()); |
There was a problem hiding this comment.
The method add_recent_profile is called on SearchQueryState but is not defined. This method needs to be implemented on the SearchQueryState type to handle adding profiles to recent search history.
| state.state = SearchState::Searched; | ||
| state.selected_index = -1; | ||
| state.user_results.clear(); | ||
| state.add_recent_query(state.string.clone()); |
There was a problem hiding this comment.
The method add_recent_query is called on SearchQueryState but is not defined. This method needs to be implemented on the SearchQueryState type to handle adding queries to recent search history.
| Some(SidePanelResponse::new(SidePanelAction::Relays, connectivity_resp)) | ||
| } else if home_resp.clicked() { | ||
| Some(SidePanelResponse::new(SidePanelAction::Home, home_resp)) | ||
| } else if opt_messages_resp.as_ref().map_or(false, |r| r.clicked()) { |
There was a problem hiding this comment.
The Messages route variant is referenced in the side panel action handling but Route::Messages is not defined in the Route enum in route.rs. This will cause a compilation error when trying to navigate to messages.
|
i cherry-picked everything that wasn't a conflict: i decided to not pick:
since it doesn't fit our theme. but maybe we can just make customizable themes in the future |

No description provided.